package jobhunter.tool;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import jobhunter.security.Current;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class ContextUtil implements Filter, ServletContextListener {

	public static ServletContext servletContext;  // Remembers the servlet context and exposes useful values to the application through static methods.
    public static ApplicationContext springContext;
    // Initialized by filter
    private static ThreadLocal<HttpServletRequest> httpServletRequest = new ThreadLocal<HttpServletRequest>();
    private static ThreadLocal<HttpServletResponse> httpServletResponse = new ThreadLocal<HttpServletResponse>();
    

	
    @Override
    public void contextInitialized(ServletContextEvent ev) {
        servletContext = ev.getServletContext();
        servletContext.setAttribute(Current.ATTRIBUTE_KEY, new Current());
        contextInitialized( WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) );
    }


   public static void contextInitialized(ApplicationContext ac) 
   {
      springContext = ac;        
    }
 
   
	public void contextDestroyed(ServletContextEvent ev) 
	{
		servletContext = null;
		springContext = null;
	}
	
	public static String getRealContextPath() 
	{
		return servletContext.getContextPath();
	}	
	
    public static ServletContext getServletContext() 
    {
		return servletContext;
	}
    
    public static boolean isInBatchNonWebMode() 
    {
    	return getServletContext() == null;
    }

    public static boolean isInWebRequestProcessingThread()
    {
        return httpServletRequest.get() != null;        
    }

    public static Object getSpringBean(String name) 
    {
        return springContext.getBean(name);
	}

    public static <T> T getSpringBean(Class<? extends T> beanClass) 
    {
        return (T)springContext.getBean(beanClass);
    }

	@Override
	public void destroy()  
	{ 
		/* Nothing to do... */ 
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException { }

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
	{
		if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) 
		{
			try
			{
	            init((HttpServletRequest)req, (HttpServletResponse)res);			
				chain.doFilter(req, res);
			} 
			catch(Throwable t)
			{
				throw t;
			}
			finally
			{
				clear();
			}
		} 
		else 
		{
			chain.doFilter(req, res);
		}
	}
	
	public static void init(HttpServletRequest req, HttpServletResponse res) 
	{
		httpServletRequest.set(req);
		httpServletResponse.set(res);
	}
	
	public static void clear() {
		httpServletRequest.set(null);
		httpServletResponse.set(null);
	}
	
	public static HttpServletRequest getHttpServletRequest() {
   return httpServletRequest.get();
	}
	public static HttpServletResponse getHttpServletResponse() {
	    if (httpServletResponse.get() == null) {
	    	throw new IllegalStateException("This thread has not been initialized by the filter. Response not found.");
	    }
	    return httpServletResponse.get();
	}
	public static HttpSession getHttpSession() {
		return getHttpServletRequest().getSession();
	}
	/** This method cares to not create a session if it does not exists (you don't want a web crawler to create a session and get 
	 * jsessionids in the urls, do you?) */
	public static Object getAttributFromHttpSession(String attributeName) {
	    HttpSession httpSession = getHttpServletRequest().getSession(false);
	    return httpSession == null ? null : httpSession.getAttribute(attributeName);
	}
}	
	
